package elementaryAlgorithm;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 郭辉
 * @className TODO
 * @description 106. 从中序与后序遍历序列构造二叉树
 * 给定两个整数数组 inorder 和 postorder ，其中 inorder 是二叉树的中序遍历， postorder 是同一棵树的后序遍历，请你构造并返回这颗 二叉树 。
 *
 *
 *
 * 示例 1:
 *
 *
 * 输入：inorder = [9,3,15,20,7], postorder = [9,15,7,20,3]
 * 输出：[3,9,20,null,null,15,7]
 * 示例 2:
 *
 * 输入：inorder = [-1], postorder = [-1]
 * 输出：[-1]
 *
 *
 * 提示:
 *
 * 1 <= inorder.length <= 3000
 * postorder.length == inorder.length
 * -3000 <= inorder[i], postorder[i] <= 3000
 * inorder 和 postorder 都由 不同 的值组成
 * postorder 中每一个值都在 inorder 中
 * inorder 保证是树的中序遍历
 * postorder 保证是树的后序遍历
 * 通过次数266,658提交次数368,745
 * @date 2023/3/21 9:44
 * @company 海康威视
 * @since 1.0.0
 */
public class Leet106 {
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        Map<Integer,Boolean> inorderVisitMap = new HashMap<>();
        Map<Integer,Integer> inorderIndexMap = new HashMap<>();
        for (int i = 0; i < inorder.length; i++) {
            inorderIndexMap.put(inorder[i],i);
            inorderVisitMap.put(i,false);
        }
        int r = inorder.length-1;
        List<Integer> list = new ArrayList<>(1);
        list.add(r);
        TreeNode root = new TreeNode(postorder[r]);
        inorderVisitMap.put(inorderIndexMap.get(postorder[r]),true);
        TreeNode node = buildTreeT(root, list, inorderIndexMap, inorderVisitMap, inorder, postorder);
        return node;
    }

    private TreeNode buildTreeT(TreeNode node, List<Integer> r, Map<Integer, Integer> inorderIndexMap, Map<Integer, Boolean> inorderVisitMap, int[] inorder, int[] postorder) {
        //左右都访问过则返回
        if ((inorderIndexMap.get(node.val) == inorder.length - 1 || inorderVisitMap.get(inorderIndexMap.get(node.val) + 1) == true )
                && (inorderIndexMap.get(node.val) == 0 || inorderVisitMap.get(inorderIndexMap.get(node.val) - 1) == true )){
            return node;
        }
        //先赋值右子树
        if (inorderIndexMap.get(node.val) != inorder.length - 1  && inorderVisitMap.get(inorderIndexMap.get(node.val) + 1) == false){
            r.set(0,r.get(0)-1);
            inorderVisitMap.put(inorderIndexMap.get(postorder[r.get(0)]),true);
            node.right  = buildTreeT(new TreeNode(postorder[r.get(0)]),r,inorderIndexMap,inorderVisitMap,inorder,postorder);
        }
        //再赋值左子树
        if (inorderIndexMap.get(node.val) != 0  && inorderVisitMap.get(inorderIndexMap.get(node.val) - 1) == false){
            r.set(0,r.get(0)-1);
            inorderVisitMap.put(inorderIndexMap.get(postorder[r.get(0)]),true);
            node.left  = buildTreeT(new TreeNode(postorder[r.get(0)]),r,inorderIndexMap,inorderVisitMap,inorder,postorder);
        }
        return node;
    }

    public static void main(String[] args) {
        int[] post = {1,2};
        int[] in = {2,1};
        Leet106 leet106 = new Leet106();
        TreeNode node = leet106.buildTree(in, post);
        System.out.println(node);
    }
}
